﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using YanShu.Handler;
using YanShu.Utils;
using Newtonsoft.Json;
using System.Windows.Controls.Primitives;
using System.Net;
using YanShu.Entity;
using YanShu.Constant;

namespace YanShu
{
    public partial class Index : Page
    {
        static Index current;
        public Index()
        {
            InitializeComponent();
            this.Loaded += Index_Loaded;
        }

        private void Index_Loaded(object sender, RoutedEventArgs e)
        {
            current = this;
            Refresh();
            account.Text = CommonUtils.ReadConfig("account");
            App.current.addMenus();
            Online();
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            String domain = "https://" + CommonUtils.ReadConfig("domain");
            addPublicDomain.Text = domain;
            https.IsChecked = true;
            addPublicPort.Text = "443";
            this.AddGrid.Visibility = Visibility.Visible;
        }

        private void Page_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            MainWindow.PageDragMove();
        }
        /// <summary>
        /// 刷新映射节点界面
        /// </summary>
        public void Refresh()
        {
            List<LanInfo> lanInfoList = CommonUtils.ReadLanInfosConfig();
            current.lanInfos.Children.Clear();
            for (int i = 0; i < lanInfoList.Count; i++)
            {
                int index = i;
                LanInfo lanInfo = lanInfoList[i];
                Border border = new Border
                {
                    Width = 250,
                    Height = 200,
                    VerticalAlignment = VerticalAlignment.Top,
                    Background = Brushes.White,
                    CornerRadius = new CornerRadius(10),
                    Margin = new Thickness(3)

                };
                current.lanInfos.Children.Add(border);

                Grid grid = new Grid();
                grid.Margin = new Thickness(10);
                RowDefinition rowDefinition1 = new RowDefinition
                {
                    Height = new GridLength(15)
                };
                RowDefinition rowDefinition2 = new RowDefinition
                {
                    Height = new GridLength(40)
                };
                RowDefinition rowDefinition3 = new RowDefinition
                {
                    Height = new GridLength(15)
                };
                grid.RowDefinitions.Add(new RowDefinition());
                grid.RowDefinitions.Add(rowDefinition1);
                grid.RowDefinitions.Add(rowDefinition2);
                grid.RowDefinitions.Add(rowDefinition3);
                grid.RowDefinitions.Add(new RowDefinition());
                grid.RowDefinitions.Add(new RowDefinition());
                grid.RowDefinitions.Add(new RowDefinition());
                bool IsChecked = false;
                if (lanInfo.GetProxyStatus() == StatusConstants.PROXY_STATUS_OPEN)
                {
                    ClientChannelHandler.Instance.OpenService(lanInfo.GetPrivateHost(), lanInfo.GetPrivatePort());
                    IsChecked = true;
                }
                ToggleButton toggleButton = new ToggleButton
                {
                    HorizontalAlignment = HorizontalAlignment.Right,
                    IsChecked = IsChecked
                };
                toggleButton.Click += (e, a) => Connect_Click(e, index);
                toggleButton.SetValue(Grid.RowProperty, 0);
                grid.Children.Add(toggleButton);
                border.Child = grid;
                TextBlock requestURL = new TextBlock
                {
                    Text = "访问地址",
                    Foreground = Brushes.DarkSlateGray
                };
                requestURL.SetValue(Grid.RowProperty, 1);
                grid.Children.Add(requestURL);
                Button publicDomain = new Button
                {
                    Content = lanInfo.GetPublicDomain(),
                    Name = "publicDomain",
                    Background = getColor("#0090CAF9"),
                    BorderBrush = getColor("#0090CAF9"),
                    Padding = new Thickness(0),
                    HorizontalAlignment = HorizontalAlignment.Left,
                    FontSize = 12,
                    Foreground = getColor("#FF2196F3"),

                };
                ContextMenu contextMenu = new ContextMenu();
                MenuItem menuItem = new MenuItem();
                menuItem.Header = "复制";
                menuItem.Click += (e, a) => Copy_Click(lanInfo.GetPublicDomain());
                contextMenu.Items.Add(menuItem);
                publicDomain.ContextMenu = contextMenu;
                publicDomain.SetValue(Grid.RowProperty, 2);
                grid.Children.Add(publicDomain);

                TextBlock privateHost = new TextBlock();
                privateHost.Text = "内网主机";
                privateHost.Foreground = Brushes.DarkSlateGray;
                privateHost.SetValue(Grid.RowProperty, 3);
                grid.Children.Add(privateHost);

                TextBlock bandwidth = new TextBlock();
                bandwidth.Text = "带宽";
                bandwidth.Foreground = Brushes.DarkSlateGray;
                bandwidth.HorizontalAlignment = HorizontalAlignment.Right;
                bandwidth.SetValue(Grid.RowProperty, 3);
                grid.Children.Add(bandwidth);

                TextBlock privateDomain = new TextBlock();
                privateDomain.Text = lanInfo.GetPrivateHost() + ":" + lanInfo.GetPrivatePort();
                privateDomain.Name = "privateDomain";
                privateDomain.Foreground = Brushes.DarkSlateGray;
                privateDomain.VerticalAlignment = VerticalAlignment.Center;
                privateDomain.SetValue(Grid.RowProperty, 4);
                grid.Children.Add(privateDomain);

                TextBlock bandwidthValue = new TextBlock();
                bandwidthValue.Text = "4M";
                bandwidthValue.Foreground = Brushes.DarkSlateGray;
                bandwidthValue.HorizontalAlignment = HorizontalAlignment.Right;
                bandwidthValue.SetValue(Grid.RowProperty, 4);
                grid.Children.Add(bandwidthValue);

                GridSplitter gridSplitter = new GridSplitter();
                gridSplitter.Height = 1;
                gridSplitter.Background = Brushes.DarkSlateGray;
                gridSplitter.HorizontalAlignment = HorizontalAlignment.Stretch;
                gridSplitter.SetValue(Grid.RowProperty, 5);
                grid.Children.Add(gridSplitter);

                Button editButton = new Button
                {
                    Width = 60,
                    Content = "编辑",
                    HorizontalAlignment = HorizontalAlignment.Right,
                    Background = getColor("#0090CAF9"),
                    BorderBrush = getColor("#0090CAF9"),
                    Foreground = Brushes.DarkSlateGray,
                };
                editButton.SetValue(Grid.RowProperty, 6);
                editButton.Click += (e, a) => Edit_Click(index);
                grid.Children.Add(editButton);

                Button deleteButton = new Button
                {
                    Width = 60,
                    Content = "删除",
                    HorizontalAlignment = HorizontalAlignment.Left,
                    Background = getColor("#0090CAF9"),
                    BorderBrush = getColor("#0090CAF9"),
                    Foreground = Brushes.DarkSlateGray,
                };
                deleteButton.SetValue(Grid.RowProperty, 6);
                deleteButton.Click += (e, a) => Del_Click(index);
                grid.Children.Add(deleteButton);

            }


        }

        private void Del_Click(int index)
        {
            CommonEntity entity = CommonUtils.ReadAllConfig();
            List<LanInfo> lanInfos = entity.GetLanInfos();
            lanInfos.RemoveAt(index);
            CommonUtils.WriteConfig(JsonConvert.SerializeObject(entity));
            Refresh();
        }

        private void Edit_Click(int index)
        {
            List<LanInfo> lanInfos = CommonUtils.ReadLanInfosConfig();
            LanInfo lanInfo = lanInfos[index];
            addPublicDomain.Text = lanInfo.GetPublicDomain();
            String port = lanInfo.GetPublicPort();
            if (port.Equals("443"))
            {
                https.IsChecked = true;
            }
            else
            {
                http.IsChecked = true;
            }
            addPublicPort.Text = port;
            addPrivateHost.Text = lanInfo.GetPrivateHost();
            addPrivatePort.Text = lanInfo.GetPrivatePort();
            this.AddGrid.Visibility = Visibility.Visible;
            this.save.Tag = index;
        }

        public SolidColorBrush getColor(String code)
        {

            Color color = (Color)ColorConverter.ConvertFromString(code);
            return new SolidColorBrush(color);
        }

        /// <summary>
        /// 上报映射信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void Connect_Click(object e, int index)
        {
            ToggleButton toggleButton = e as ToggleButton;
            CommonEntity entity = CommonUtils.ReadAllConfig();
            List<LanInfo> lanInfos = entity.GetLanInfos();
            LanInfo lanInfo = lanInfos[index];
            if (toggleButton.IsChecked == true)
            {
                for (int i = 0; i < lanInfos.Count; i++)
                {
                    if (i != index && lanInfo.GetPublicDomain().Equals(lanInfos[i].GetPublicDomain()) && lanInfos[i].GetProxyStatus() == StatusConstants.PROXY_STATUS_OPEN)
                    {
                        toggleButton.IsChecked = false;
                        App.ShowBalloonTip("注意", "已存在打开的域名!");
                        return;
                    }
                }
                lanInfo.SetProxyStatus(StatusConstants.PROXY_STATUS_OPEN);
                ClientChannelHandler.Instance.OpenService(lanInfo.GetPrivateHost(), lanInfo.GetPrivatePort());
            }
            else
            {
                lanInfo.SetProxyStatus(StatusConstants.PROXY_STATUS_CLOSE);
            }
            CommonUtils.WriteConfig(JsonConvert.SerializeObject(entity));
        }


        private void Close_Click(object sender, RoutedEventArgs e)
        {
            MainWindow.HideWindow();
        }

        private void PublicDomain_Click(object sender, RoutedEventArgs e)
        {
            Button btn = sender as Button;
            System.Diagnostics.Process.Start((String)btn.Content);
        }

        private void Copy_Click(String domain)
        {
            Clipboard.SetText(domain);
            App.ShowBalloonTip("提示", "已复制访问地址到剪切板！");
        }

        private void Return_Click(object sender, RoutedEventArgs e)
        {
            AddGrid.Visibility = Visibility.Hidden;
        }
        private void Save_Click(object sender, RoutedEventArgs e)
        {
            String publicDomain = this.addPublicDomain.Text;
            String publicPort = this.addPublicPort.Text;
            String privateHost = this.addPrivateHost.Text;
            String privatePort = this.addPrivatePort.Text;
            CommonEntity entity = CommonUtils.ReadAllConfig();
            List<LanInfo> lanInfos = entity.GetLanInfos();
            String tag = save.Tag.ToString();
            if (!checkParams(privateHost, privatePort))
            {
                return;
            }
            if (tag.Equals("add"))
            {
                LanInfo lanInfo = new LanInfo();
                // 默认打开
                lanInfo.SetProxyStatus(1);
                foreach (LanInfo lan in lanInfos)
                {
                    //协议、域名相同
                    if (lan.GetPublicDomain().Equals(publicDomain))
                    {
                        //已开启
                        if (lan.GetProxyStatus() == 1)
                        {
                            lanInfo.SetProxyStatus(0);
                        }
                    }
                }
                lanInfo.SetPublicDomain(publicDomain);
                lanInfo.SetPublicPort(publicPort);
                lanInfo.SetPrivateHost(privateHost);
                lanInfo.SetPrivatePort(privatePort);
                lanInfos.Add(lanInfo);
            }
            else
            {
                int index = int.Parse(tag);
                LanInfo lanInfo = lanInfos[index];
                lanInfo.SetPublicDomain(publicDomain);
                lanInfo.SetPublicPort(publicPort);
                lanInfo.SetPrivateHost(privateHost);
                lanInfo.SetPrivatePort(privatePort);
            }
            save.Tag = "add";
            CommonUtils.WriteConfig(JsonConvert.SerializeObject(entity));
            AddGrid.Visibility = Visibility.Hidden;
            Refresh();
        }
        /// <summary>
        /// 校验内网主机端口
        /// </summary>
        /// <param name="privateHost"></param>
        /// <param name="privatePort"></param>
        /// <returns></returns>
        private bool checkParams(String privateHost, String privatePort)
        {
            privateHostTip.Text = "";
            privatePortTip.Text = "";
            //校验内网主机是否合法
            if (privateHost == "")
            {
                privateHostTip.Text = "内网主机不能为空!";
                return false;
            }

            if (!privateHost.Equals("localhost") && !IPAddress.TryParse(privateHost, out _))
            {
                privateHostTip.Text = "内网主机格式不正确!";
                return false;
            }
            if (privatePort == "")
            {
                privatePortTip.Text = "端口不能为空!";
                return false;
            }
            if (!int.TryParse(privatePort, out int port) || port < 0 || port > 65535)
            {
                privatePortTip.Text = "端口格式不正确!";
                return false;
            }
            return true;
        }

        private void Http_Click(object sender, RoutedEventArgs e)
        {
            addPublicPort.Text = "80";
            addPublicDomain.Text = addPublicDomain.Text.Replace("https://", "http://");
        }

        private void Https_Click(object sender, RoutedEventArgs e)
        {
            addPublicPort.Text = "443";
            addPublicDomain.Text = addPublicDomain.Text.Replace("http://", "https://");
        }

        public static void Offline()
        {
            if (current != null)
            {
                current.stautsIcon.Background = Brushes.DarkGray;
            }
        }
        public static void Online()
        {
            //为空则是初始化。无需变动
            if (current!=null)
            {
                Color color = (Color)ColorConverter.ConvertFromString("#FF10E01F");
                current.stautsIcon.Background = new SolidColorBrush(color);
            }
        }
    }
}
